/**==============================================================================
            Copyright (c) 2013 Moritz Hader, Marcel Schrder
            All Rights Reserved.

	@file  HeimdallEGLConfigChooser.java

	@brief  This class is used by the GLSurfaceView to choose the right egl-context. 
	Therefore, we provide the buffer-size for RGBA as well as Stencil and depth buffer 
	and read the possible configurations our hardware/software supports. The method 
	chooseConfig automatically returns the configuration that meets the requirements 
	if there is any.

  This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
==============================================================================*/
package de.ibm.dhbw.heimdall.egl;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;

import android.opengl.GLSurfaceView;

/**
 * 
 * @author moritzhader
 *
 */
public class HeimdallEGLConfigChooser implements GLSurfaceView.EGLConfigChooser{
	
	private static Logger Log = Logger.getLogger(HeimdallEGLConfigChooser.class.getCanonicalName());

	private int HRed;
	private int HGreen;
	private int HBlue;
	private int HAlpha;
	private int HDepth;
	private int HStencil;
	
	
	public HeimdallEGLConfigChooser(int red, int green, int blue, int alpha, int depth, int stencil){
		this.HRed = red;
		this.HGreen = green;
		this.HBlue = blue;
		this.HAlpha = alpha;
		this.HDepth = depth;
		this.HStencil = stencil;
		
		Log.log(Level.INFO, "Initializing ContextConfiguration with parameters [r: "+red+" g: "+green+" b: "+blue+" a: "+alpha+" s: "+stencil+" d: "+depth+"]");
	}
	
	@Override
	public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
		Log.log(Level.INFO, "Choosing configuration. Using minimum configuration [4,4,4,0x0004]");
		
		/*
		 * Like the configuration of the context, we will need an attribute-list.
		 * This attribute list defines the minimum configuration we will need for our
		 * context.
		 */
		int[] attributes = {
				EGL10.EGL_RED_SIZE, 4,
				EGL10.EGL_GREEN_SIZE, 4,
				EGL10.EGL_BLUE_SIZE, 4,
				EGL10.EGL_RENDERABLE_TYPE, 0x0004, //Renderables will be of type EGL2.0 (which is 0x4)
				EGL10.EGL_NONE
		};
		
		int[] num_config = new int[1]; //Store the count of possible configurations that meet our requirements
		egl.eglChooseConfig(display, attributes, null, 0, num_config);
		
		if(num_config[0] <= 0){
			
			Log.log(Level.SEVERE, "Error: The ContextConfiguration could not be initialized with the provided minimum-configuration.");
			
			return null;
		}
		
		Log.log(Level.INFO, "Found "+num_config[0]+" possible configurations for the minimum setting.");
		
		//Now that we know how many possible configurations there are, we can load the actual configurations from EGL
		EGLConfig configs[] = new EGLConfig[num_config[0]];
		
			int config_size = num_config[0]; //The eglChooseConfig method might overwrite the num_config array
			egl.eglChooseConfig(display, attributes, configs, config_size, num_config);
			
		/*
		 * So far, the configs array contains every configuration that the given device supports using the minimum configuration.
		 * The only thing we need to do now, is to find the configuration that matches our requirements.
		 */
		
		for(EGLConfig conf:configs){
			//We now compare the atributes supplied by the configruation with our expectations (Note, we reuse the num_config field here)
			
			//Depth
			egl.eglGetConfigAttrib(display, conf, EGL10.EGL_DEPTH_SIZE, num_config);
			int depth = num_config[0];
			
			//Stencil
			egl.eglGetConfigAttrib(display, conf, EGL10.EGL_STENCIL_SIZE, num_config);
			int stencil = num_config[0];
			
			//Red
			egl.eglGetConfigAttrib(display, conf, EGL10.EGL_RED_SIZE, num_config);
			int red = num_config[0];
			
			//Green
			egl.eglGetConfigAttrib(display, conf, EGL10.EGL_GREEN_SIZE, num_config);
			int green = num_config[0];
			
			//Blue
			egl.eglGetConfigAttrib(display, conf, EGL10.EGL_BLUE_SIZE, num_config);
			int blue = num_config[0];
			
			//Alpha
			egl.eglGetConfigAttrib(display, conf, EGL10.EGL_ALPHA_SIZE, num_config);
			int alpha = num_config[0];
			
			Log.log(Level.INFO, "Found ContextConfiguration with parameters [r: "+red+" g: "+green+" b: "+blue+" a: "+alpha+" s: "+stencil+" d: "+depth+"]");
			
			if (depth < this.HDepth | stencil < this.HStencil){ //If the stencil and depth does not fit, skip this config
				continue;
			}
			
			//If it now matches the rgba preferences, then we've found our configuration
			if(red == this.HRed && green == this.HGreen && blue == this.HBlue && alpha == this.HAlpha){ 
				return conf;
			}
		}
		
		Log.log(Level.INFO,"No fitting configuration was found");
		return null;
	}

}
